//
//  ViewController.m
//  GJWebRTCDemo
//
//  Created by 吴棒棒 on 2021/10/26.
//

#import "ViewController.h"
#import "XMPPManager/XMPPManager.h"
#import <WebRTC/WebRTC.h>
#import "RTCSessionDescription+JSON.h"
#import <WebRTC/RTCDefaultVideoDecoderFactory.h>
#import <WebRTC/RTCDefaultVideoEncoderFactory.h>
@interface ViewController ()<XMPPManagerDelegate, RTCPeerConnectionDelegate,RTCVideoViewDelegate>
@property(nonatomic, strong) RTCPeerConnectionFactory *factory;
@property (nonatomic, strong) RTCCameraPreviewView *localVideoView;
@property(nonatomic, strong) RTCMediaStream *localStream;
@property(nonatomic, strong) RTCPeerConnection *connection;
@property(nonatomic, strong) RTCAudioTrack *audioTrack ;
@property(nonatomic, strong) RTCVideoTrack *videoTrack;
@property(nonatomic, strong) RTCEAGLVideoView *remoteView ;

@property(nonatomic, assign) NSInteger count;
@property(nonatomic,strong) NSTimer *timer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    /// xmpp 建联   登录
    NSString *userName = @"wbb";
    NSString *userPassword = @"wbb123";
    NSString *serverIP = @"172.16.103.12";
    [self loginWith:userName pwd:userPassword serverIP:serverIP];
    
    self.localVideoView = [[RTCCameraPreviewView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
    [self.view addSubview:self.localVideoView];
    
    
 

    RTCAudioSessionConfiguration *webRTCConfig =
    [RTCAudioSessionConfiguration webRTCConfiguration];
    webRTCConfig.categoryOptions = webRTCConfig.categoryOptions |
    AVAudioSessionCategoryOptionDefaultToSpeaker;
    
    //        webRTCConfig.ioBufferDuration=1;
    webRTCConfig.sampleRate=kRTCAudioSessionLowComplexitySampleRate;
//       webRTCConfig.ioBufferDuration=0.2;
    //        RDLog(@"ioBufferDuration:%f",kRTCAudioSessionHighPerformanceIOBufferDuration);
    [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig];
    
  
    RTCDefaultVideoEncoderFactory * encoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init];

    RTCDefaultVideoDecoderFactory*  decoderFactory = [[RTCDefaultVideoDecoderFactory alloc] init];

    self.factory= [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory
                                                  decoderFactory:decoderFactory];
    
    [self createLocalStream1];
    
    [self createPeerConnections];
    
//    [self addSdpTimer];
    
}
- (void)addSdpTimer {
    
    NSString *str = self.connection.localDescription.sdp;
    NSLog(@"publisherPeerConnection ======== %@", str);
    if (str) {
        [self offerSdp:str];
    }
    
    
}
- (IBAction)xmppClick:(UIButton *)sender {
    [self sendMessage];

}
- (void)createLocalStream1 {
    
    if (_localStream == nil)
    {
        //如果为空，则创建点对点工厂
        
        NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
        //        AVCaptureDevicePosition position = _usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
        
        AVCaptureDevice * device = captureDevices[0];
        for (AVCaptureDevice *obj in captureDevices)
        {
            if (obj.position == AVCaptureDevicePositionFront)
            {
                device = obj;
                break;
            }
        }
        //检测摄像头权限
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
        {
            NSLog(@"相机访问受限");
        }
        else
        {
            if (device)
            {
                //创建本地流
                _localStream = [_factory mediaStreamWithStreamId:@"ARDAMS"];
                //获取数据源
                RTCVideoSource *_source = [_factory videoSource];
                
                //音频
//                RTCAudioTrack * audioTrack = [_factory audioTrackWithTrackId:@"ARDAMSa0"];
                RTCMediaConstraints *constraints = [self defaultMediaAudioConstraints];
                RTCAudioSource *source = [_factory audioSourceWithConstraints:constraints];
                RTCAudioTrack *audioTrack = [_factory audioTrackWithSource:source trackId:@"ARDAMSa0"];
                self.audioTrack = audioTrack;
                //视频
                RTCVideoTrack *videoTrack = [_factory videoTrackWithSource:_source trackId:@"ARDAMSv0"];
                self.videoTrack = videoTrack;
                //将audioTrack、videoTrack添加到流
//                [_localStream addAudioTrack:audioTrack];
//                [_localStream addVideoTrack:videoTrack];
                //拿到capture对象
                RTCCameraVideoCapturer * capture = [[RTCCameraVideoCapturer alloc] initWithDelegate:_source];
                AVCaptureDeviceFormat * format = [[RTCCameraVideoCapturer supportedFormatsForDevice:device] lastObject];
                CGFloat fps = [[format videoSupportedFrameRateRanges] firstObject].maxFrameRate;
                
                [capture startCaptureWithDevice:device format:format fps:fps completionHandler:^(NSError * error) {
                    NSLog(@"startCaptureWithDevice---：%@",error);
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        //展示预览
                        [self.localVideoView setCaptureSession:[capture captureSession] ];
                    });
                }];
            }
            else
            {
                NSLog(@"该设备不能打开摄像头");
            }
        }
    }
}
- (RTCMediaConstraints *)defaultMediaAudioConstraints {
    
    NSDictionary *mandatoryConstraints = @{@"noiseSuppression": @"true",@"echoCancellation": @"true"};
    RTCMediaConstraints *constraints =
    [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints
                                          optionalConstraints:nil];
    return constraints;
}
/**
 *  创建所有连接
 */
 - (void)createPeerConnections
{
    RTCPeerConnection *connection = [self createPeerConnection];
    self.connection = connection;

//    [self.connection addStream:_localStream];
    
    [self createAudioSender:connection];
    [self createVideoSender:connection];

}
- (RTCRtpSender *)createAudioSender:(RTCPeerConnection *)peerConnection {
    RTCRtpSender *sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindAudio streamId:@"ARDAMS"];
    if (self.audioTrack ) {
        sender.track = self.audioTrack ;
    }
    return sender;
}
- (RTCRtpSender *)createVideoSender:(RTCPeerConnection *)peerConnection {
    RTCRtpSender *sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo
                                                 streamId:@"ARDAMS"];
    if (self.videoTrack) {
        sender.track = self.videoTrack;
    }

    return sender;
}
- (RTCPeerConnection *)createPeerConnection
{
    RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints];
    RTCConfiguration *config = [[RTCConfiguration alloc] init];
    NSMutableArray *iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
    config.iceServers = iceServers;
    config.iceTransportPolicy = RTCIceTransportPolicyAll;
//    config.sdpSemantics = RTCSdpSemanticsUnifiedPlan;
    RTCPeerConnection *peerConnection = [_factory peerConnectionWithConfiguration:config
                                         constraints:constraints
                                            delegate:self];
    return peerConnection;
}
- (RTCMediaConstraints *)defaultPeerConnectionConstraints
{
    NSDictionary *optionalConstraints = @{ @"DtlsSrtpKeyAgreement" : @"true" };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil  optionalConstraints:optionalConstraints];
    return constraints;
}

- (RTCIceServer *)defaultSTUNServer {
    NSArray *array = [NSArray arrayWithObject:@"stun:47.114.110.197:23478"];
    RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:array
                                                              username:@""
                                                            credential:@"" tlsCertPolicy:RTCTlsCertPolicyInsecureNoCheck];
    return iceServer;
}
- (RTCMediaConstraints *)creatConstraintWithOption{
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{kRTCMediaConstraintsOfferToReceiveAudio:kRTCMediaConstraintsValueTrue,kRTCMediaConstraintsOfferToReceiveVideo:kRTCMediaConstraintsValueTrue} optionalConstraints:nil];
    return constraints;
}
- (RTCMediaConstraints *)defaultOfferConstraints {
    NSDictionary *mandatoryConstraints = @{
                                           @"OfferToReceiveAudio" : @"true",
                                           @"OfferToReceiveVideo" : @"false"
                                           };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints optionalConstraints:nil];
    return constraints;
}

- (void)onPublisherRemoteJsep:(NSNumber *)handleId dict:(NSDictionary *)jsep {
    
    
    
    __weak typeof(self) weakself = self;//ARC

    RTCSessionDescription *answerDescription = [RTCSessionDescription descriptionFromJSONDictionary:jsep];
    [self.connection setRemoteDescription:answerDescription completionHandler:^(NSError * _Nullable error) {
        __strong typeof(self) strongSelf = weakself;//ARC

        if(error) {
            NSLog(@"ERROR ==== %@", error);
        }else {
            [strongSelf offerPeerConnection:@0];
        }
    }];
}
- (void)offerPeerConnection: (NSNumber*) handleId {
    
    //    [self createDataChannelWithPeerConnection:publisherPeerConnection connectionId:[NSString stringWithFormat:@"%@",handleId]];
    
    __weak typeof(self) weakself = self;//ARC

    [self.connection answerForConstraints:[self defaultOfferConstraints]
                        completionHandler:^(RTCSessionDescription *sdp,
                                            NSError *error) {
        __strong typeof(self) strongSelf = weakself;//ARC

        [strongSelf.connection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
            [self offerSdp:sdp.sdp];
            if (!error) {
                NSLog(@"Successed to set local offer sdp!");

//                [self performSelector:@selector(addSdpTimer) withObject:nil afterDelay:2];

            }else{
                NSLog(@"Failed to set local offer sdp, err=%@", error);

            }
        }];
        
        
    }];
    
    
}
- (void)delayMethod {
    NSLog(@"self.connection.localDescription.sdp ===== %@", self.connection.localDescription.sdp);

}
/** Called when the SignalingState changed. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didChangeSignalingState:(RTCSignalingState)stateChanged{
    NSLog(@"didChangeSignalingState");
}

/** Called when media is received on a new stream from remote peer. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection didAddStream:(RTCMediaStream *)stream {
    NSLog(@"didAddStream");
    dispatch_async(dispatch_get_main_queue(), ^{
        if (stream.videoTracks.count) {
            RTCVideoTrack *remoteVideoTrack = stream.videoTracks[0];
            RTCEAGLVideoView *remoteView = [self createRemoteView];
            [remoteVideoTrack addRenderer:remoteView];
//            self.videoTrack=remoteVideoTrack;
        }
    });
}
- (RTCEAGLVideoView *)createRemoteView {
 
    RTCEAGLVideoView *remoteView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectMake(0, 300, 480, 360)];
    remoteView.delegate = self;
    [self.view addSubview:remoteView];
    return remoteView;
}
/** Called when a remote peer closes a stream.
 *  This is not called when RTCSdpSemanticsUnifiedPlan is specified.
 */
- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveStream:(RTCMediaStream *)stream{
    NSLog(@"didRemoveStream");

}

/** Called when negotiation is needed, for example ICE has restarted. */
- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection{
    NSLog(@"peerConnectionShouldNegotiate");

}

/** Called any time the IceConnectionState changes. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didChangeIceConnectionState:(RTCIceConnectionState)newState{
    NSLog(@"didChangeIceConnectionState");

}

/** Called any time the IceGatheringState changes. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didChangeIceGatheringState:(RTCIceGatheringState)newState{
    NSLog(@"didChangeIceGatheringState");

}

/** New ice candidate has been found. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didGenerateIceCandidate:(RTCIceCandidate *)candidate{
    NSLog(@"didGenerateIceCandidate ============= %@", candidate);
    self.count = 0;
//    [self offerSdp:candidate.sdp];
}

/** Called when a group of local Ice candidates have been removed. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didRemoveIceCandidates:(NSArray<RTCIceCandidate *> *)candidates{
    NSLog(@"didRemoveIceCandidates");

}

/** New data channel has been opened. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
    didOpenDataChannel:(RTCDataChannel *)dataChannel{
    NSLog(@"didOpenDataChannel");

}





//登录页面代理回调用户名和密码
- (void)loginWith:(NSString *)userName pwd:(NSString *)pwd serverIP:(NSString *)ip
{
    //初始化服务器连接管理

    [XMPPManager manager].theHostIP=ip;
    [XMPPManager manager].delegate = self;
    [[XMPPManager manager] setUserName:userName password:pwd];
    BOOL coonect = [[XMPPManager manager] connectServer];
    if (coonect) {
        NSLog(@"连接成功");

    }
    else
    {
        NSLog(@"连接失败");
    }
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self sendMessage];
}
#pragma mark XMPPManager 代理；

//收到消息
- (void)didReceiveMessage:(XMPPMessage *)message
{

    if(message==nil)
    {
        return;
    }
    NSString *body = [[message elementForName:@"body"] stringValue];
//    NSString *displayName = [[message from] user];
    NSData *data = [body dataUsingEncoding:NSUTF8StringEncoding];
    if(data!=nil)
    {
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"didReceiveMessage:%@",dic);
        if([dic[@"id"] intValue] == 0) {
            NSDictionary *result_dic = dic[@"result"];
            if ([result_dic[@"message"] isEqualToString:@"success"]) {
                NSDictionary * sdp_dic=[result_dic objectForKey:@"sdp"];

                [self onPublisherRemoteJsep:@0 dict:sdp_dic];

            }
        }

    }

}
//用户登录
- (void)userLoginSuccess:(XMPPJID *)userJID
{
    NSLog(@"用户：%@ 登录成功",userJID.user);
    XMPPPresence *presence = [XMPPPresence presence];
    NSString *toStr = @"dev_6_18@guiji.ai";
    [presence addAttributeWithName:@"type" stringValue:@"available"];
    [presence addAttributeWithName:@"to" stringValue:toStr];
    [[XMPPManager manager].xmppStream sendElement:presence];
//    [self offerPeerConnection:@0];
}

//新用户在线
- (void)newUserOnline:(XMPPPresence *)presence
{
    NSString *user = [[presence from] user];
    NSLog(@"发现用户：%@ 上线",user);

}

//用户下线
- (void)hasUserOffline:(XMPPPresence *)presence
{
    NSString *user = [[presence from] user];
    NSLog(@"发现用户：%@ 离线",user);
//    [self onLeaving:0];
}

- (void)sendMessage
{
    NSDictionary* bodydic = @{
        
        @"method":@"MakeNewSession",
        
        @"params":@{
            
            @"sessionId":@"2bd3fa34-21da-4762-8fdc-7e92e4cec8b4",
            
            @"dumpSession":@1,
            
            @"data":@{
                
                @"bg_img":@"https://robot.guiji.ai/nfs/duix-cc/background/MetaHumanSample.png",
                
                @"sequence":@[
                    
                    @"https://kun.guiji.ai/model/2021/10/14/25dea00922e94b7b83996447abb6fb86.mp4"
                    
                ],
                
                @"udCode":@"213354538352709"
                
            }
            
        },
        
        @"id":@0
        
    };
    
    NSData *bodyData = [NSJSONSerialization dataWithJSONObject:bodydic options:NSJSONWritingPrettyPrinted error:nil];
    if (bodyData!=nil)
    {
        NSString *body_str = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
        NSString *toStr = @"dev_6_18@guiji.ai";
        
        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
        [body setStringValue:body_str];
        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
        [message addAttributeWithName:@"type" stringValue:@"chat"];
        [message addAttributeWithName:@"to" stringValue:toStr];
        [message addChild:body];
        
        
        
        NSLog(@"发送消息给XMPP:%@",message);
        
        [[XMPPManager manager].xmppStream sendElement:message];
    }
    
    
}
- (void)offerSdp:(NSString *)sdp {

    NSDictionary *bodydic = @{
        @"method":@"AnswerSession",
        @"params":@{
            @"sdp":@{
                @"type":@"answer",
                @"sdp":sdp
            },
            @"sessionId":@"2bd3fa34-21da-4762-8fdc-7e92e4cec8b4"
        },
        @"id":@1
    };
    
    NSData *bodyData = [NSJSONSerialization dataWithJSONObject:bodydic options:NSJSONWritingPrettyPrinted error:nil];
    if (bodyData!=nil)
    {
        NSString *body_str = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
        
        NSLog(@"bodydic ===== %@", body_str);

        NSString *toStr = @"dev_6_18@guiji.ai";
        
        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
        [body setStringValue:body_str];
        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
        [message addAttributeWithName:@"type" stringValue:@"chat"];
        [message addAttributeWithName:@"to" stringValue:toStr];
        [message addChild:body];
        
        
        
        NSLog(@"发送消息给XMPP:%@",message);
        
        [[XMPPManager manager].xmppStream sendElement:message];
    }
}
- (void)videoView:(id<RTCVideoRenderer>)videoView didChangeVideoSize:(CGSize)size
{
    
//    CGRect rect = videoView.frame;
//    rect.size = size;
//    NSLog(@"========didChangeVideiSize %fx%f", size.width, size.height);
    [videoView setSize:size];
    
}
@end
